<template>
  <echarts class="bi-bar" ref="echartRef" />
</template>
<script setup>
import echarts from "@/components/echarts/index.vue"
import { options, echartsDataset } from "@/components/echarts/echarts"
import { useVisual } from "@/hooks/userEditor"
import { deepAssign, gradientColor } from "@/utils/util"
const { commonStyle } = useVisual()
const attrs = useAttrs()
const option = attrs.option
let { dimension, measure, aggregation } = attrs.data
const echartRef = ref(null)
let setOptions = {}
let dataset = {
  dimensions: [],
  source: []
}
watch(
  attrs.data,
  (val) => {
    dimension = val.dimension
    measure = val.measure
    aggregation = val.aggregation
  },
  { deep: true, immediate: true }
)
watch(
  [option, commonStyle],
  () => {
    init()
  },
  { deep: true }
)
const init = () => {
  const settings = g.Copy(option)
  setOptions = options(settings)
  setOptions.dataset = dataset
  const seriesLabel = settings.label
  if (!option?.label?.color) {
    seriesLabel.color = commonStyle.value.theme === "dark" ? "#fff" : "#000"
  }
  settings.seriesbar.label = seriesLabel
  settings.seriesLine.label = seriesLabel
  // 是否换行
  if (settings.xAxis.axisLabel.overflow) {
    settings[!settings.horizontal ? "xAxis" : "yAxis"].axisLabel.overflow = "break"
    settings[!settings.horizontal ? "xAxis" : "yAxis"].axisLabel.formatter = (val) => {
      return val
    }
  }
  if (settings.metrics && Object.keys(settings.metrics).length > 0) {
    const yAxis = []
    Object.keys(settings.metrics).forEach((item) => {
      yAxis.push({
        ...settings.yAxis,
        position: settings.metrics[item].yAxisIndex === 0 ? "left" : "right",
        offset: settings.metrics[item].yAxisIndex * 50
      })
    })
    settings.grid.right =
      settings.grid.right + g.max(Object.values(settings.metrics).map((item) => item.yAxisIndex)) * 50
    setOptions.yAxis = yAxis
  }
  setOptions.series = measure.map((item) => {
    const metricsField = g.Copy(settings.metrics[item.field] || [])
    settings.label.formatter = (params) => {
      return `${params.value[params.dimensionNames[params.encode.y[0]]]}${item.format.includes("PERCENT") ? "%" : ""}`
    }
    if (metricsField && metricsField?.itemStyle?.color) {
      const colors = gradientColor(metricsField.itemStyle.color).splice(0, 2).filter(Boolean)
      if (colors.length > 1) {
        // 渐变色
        const colorStops = colors.map((item, index) => {
          return {
            offset: index / (colors.length - 1),
            color: item
          }
        })
        metricsField.itemStyle.color = {
          type: "linear",
          x: 0,
          y: 0,
          x2: 0,
          y2: 1,
          colorStops,
          global: false // 缺省为 false
        }
      }
    }
    if (metricsField.type === "line") {
      settings.seriesLine.lineStyle.color = g.Copy(metricsField.itemStyle.color)
      if (settings.seriesLine.areaStyleShow) {
        settings.seriesLine.areaStyle = {}
      }
    }
    ;["markPoint", "markLine"].forEach((v) => {
      Object.values(metricsField[v].option).forEach((item) => {
        if (item.show) {
          item.label = {
            color: metricsField[v].label.color || commonStyle.value.theme === "dark" ? "#fff" : "#000",
            position: "middle"
          }
          metricsField[v].data.push({
            name: "最大",
            type: item.type,
            label: item.label
          })
        }
      })
    })
    return {
      type: option.metrics[item.field]?.type || "bar",
      stack: settings.stack ? "total" : "",
      label: settings.label,
      ...deepAssign(g.Copy(metricsField.type === "line" ? settings.seriesLine : settings.seriesbar), metricsField)
    }
  })
  setOptions.series.forEach((item) => {
    if (!settings.label.show) {
      item.label.show = false
    }
  })
  echartRef.value.init(setOptions)
}
// 对外暴露的方法，接收外部传入的数据
const update = (data) => {
  dataset = echartsDataset(data, dimension, measure, aggregation)
  const obj = {}
  measure.forEach((item, index) => {
    obj[item.field] = g.extend(
      {
        index,
        name: item.title,
        type: "bar",
        yAxisIndex: 0,
        label: {
          show: true
        },
        itemStyle: {},
        lineStyle: {},
        markPoint: {
          option: {
            max: {
              show: false,
              type: "max",
              label: {},
              itemStyle: {}
            },
            min: {
              show: false,
              type: "min",
              label: {},
              itemStyle: {}
            },
            average: {
              show: false,
              type: "average",
              label: {},
              itemStyle: {}
            }
          },
          data: [],
          label: {},
          itemStyle: {}
        },
        markLine: {
          option: {
            max: {
              show: false,
              type: "max",
              label: {},
              itemStyle: {}
            },
            min: {
              show: false,
              type: "min",
              label: {},
              itemStyle: {}
            },
            average: {
              show: false,
              type: "average",
              label: {},
              itemStyle: {}
            },
            median: {
              show: false,
              type: "median",
              label: {},
              itemStyle: {}
            }
          },
          data: [],
          label: {},
          itemStyle: {}
        }
      },
      option?.metrics[item.field]
    )
  })
  option.metrics = obj
  init()
}
defineExpose({
  update
})

onBeforeUnmount(() => {
  echartRef?.value?.dispose()
})
</script>
<style scoped lang="less">
.bi-bar {
  width: 100%;
  height: 100%;
}
</style>
